#include "util/mempool.h"
#include "base/config.h"

#include <malloc.h>
#include <cstring>

#include <iostream>

#include "base/base_buffer.h"
namespace net_tools::base
{

  util::Memorypool *Base_buffer::mempool_ = nullptr;

  Base_buffer::Base_buffer(int block_number)
      : write_index_(0),
        read_index_(0),
        buf_size_(block_number * _C::BUFFER_MEMPOOL_BLOCK_SIZE),
        next_(this),
        before_(this)
  {
    if (mempool_)
    {
      buf_ = mempool_->Get_memory_locked(block_number);
      if (!buf_)
      { //内存池空了
        free_ = true;
        buf_ = malloc(buf_size_);
      }
      else
      {
        free_ = false;
      }
    }
    else
    {
      free_ = true;
      buf_ = malloc(buf_size_);
    }
    if (!buf_) [[unlikely]]
    {
      std::cout << "内存耗尽" << std::endl;
      exit(0);
    }
  };

  Base_buffer::~Base_buffer()
  {
    if (free_)
    {
      free(buf_);
    }
    else
    {
      mempool_->Free_memory_locked(buf_);
    }
  }

  void Base_buffer::Write(void *buf, unsigned int size)
  {
    memcpy(Write_index(), buf, size);
    write_index_ += size;
  };

  void Base_buffer::Singleton_pool(int mempool_block_size, int mempool_block_number)
  {
    static util::Memorypool mempool(mempool_block_size, mempool_block_number);
    mempool_ = &mempool;
  };

  char *Base_buffer::operator[](unsigned int index)
  {
    return reinterpret_cast<char *>(buf_) + read_index_ + index;
  };

  // self -> other => self -> next -> other
  void Base_buffer::Insert_next(Base_buffer *next)
  {
    this->next_->before_ = next;
    next->next_ = this->next_;
    this->next_ = next;
    next->before_ = this;
  };

  // other -> self => other -> pre -> self
  void Base_buffer::Insert_pre(Base_buffer *pre)
  {
    this->before_->next_ = pre;
    pre->before_ = this->before_;
    this->before_ = pre;
    pre->next_ = this;
  };

} // net_tools::base